<template>
  <div>
    <div
      class="chart"
      style="position: absolute;"
      :style="chartStyle"
      @mousedown.stop="down"
      @mouseup.stop="up"
      @mousemove="move"
      @click.stop="setActive(true)"
    ></div>
    <div v-show="active">
      <img @click.stop="removeChart" :style="closeStyle" src="@/assets/image/canvas/chart/关闭.png" />

      <img
        @click.stop="downloadByPeople"
        :style="deriveStyle"
        src="@/assets/image/canvas/chart/导出.png"
      />

      <img
        @mousedown.stop="resizeDown($event, 'leftTop')"
        :style="leftTopStyle"
        class="leftTop"
        src="@/assets/image/canvas/chart/边角左上.png"
      />
      <img
        @mousedown.stop="resizeDown($event, 'rightTop')"
        :style="rightTopStyle"
        class="rightTop"
        src="@/assets/image/canvas/chart/边角右上.png"
      />
      <img
        @mousedown.stop="resizeDown($event, 'leftBottom')"
        :style="leftBottomStyle"
        class="leftBottom"
        src="@/assets/image/canvas/chart/边角左下.png"
      />
      <img
        @mousedown.stop="resizeDown($event, 'rightBottom')"
        class="rightBottom"
        :style="rightBottomStyle"
        src="@/assets/image/canvas/chart/边角右下.png"
      />
    </div>
  </div>
</template>

<script>
import $ from "jquery";
import Utils from "@/Utils/Utils.js";
export default {
  props: [
    "type",
    "columns",
    "values",
    "positionX",
    "positionY",
    "moveActive",
    "active",
    "chartIndex",
    "canvasIndex",
    "axis", //轴的字段名称和表名
    "value", //值的字段名称和表名
    "zindex", //z-index
    "title",
    "titleLeft",
    "titleColor",
    "width", //图表的宽度
    "height", //图表的宽度
    "theX",
    "theY",
    "echarts",
    "way",
    "fontsize",
    "canvasStartX",
    "canvasEndX",
    "canvasStartY",
    "canvasEndY",
    "clusterCount",
    "darkMode",

    "xAxisShow",
    "xAxisName",
    "xAxisNameLocation",
    "xAxisNameColor",
    "xAxisOffset",
    "xAxisFontSize",
    "xAxisPosition",

    "yAxisShow",
    "yAxisName",
    "yAxisNameLocation",
    "yAxisNameColor",
    "yAxisOffset",
    "yAxisFontSize",
    "yAxisPosition",

    "legendType",
    "legendShow",
    "legendLeft",
    "legendTop",
    "legendWidth",
    "legendHeight",
    "legendOrient",
    "legendColor",
    "legendFontSize",
  ],
  computed: {
    chartStyle() {
      return {
        left: this.theX + "px",
        top: this.theY + "px",
        width: this.width + "px",
        height: this.height + "px",
        zIndex: this.zindex,
      };
    },

    leftTopStyle() {
      return {
        position: "absolute",
        left: this.theX - 2 + "px",
        top: this.theY - 2 + "px",
      };
    },

    rightTopStyle() {
      return {
        position: "absolute",
        left: this.theX - 17 + this.width + "px",
        top: this.theY - 2 + "px",
      };
    },

    leftBottomStyle() {
      return {
        position: "absolute",
        left: this.theX - 2 + "px",
        top: this.theY + this.height - 17 + "px",
      };
    },

    closeStyle() {
      return {
        position: "absolute",
        left: this.theX + this.width - 24 + "px",
        top: this.theY + 30 + "px",
        "z-index": 200,
      };
    },

    deriveStyle() {
      return {
        position: "absolute",
        left: this.theX + this.width - 22 + "px",
        top: this.theY + 55 + "px",
        "z-index": 200,
      };
    },

    rightBottomStyle() {
      return {
        position: "absolute",
        left: this.theX + this.width - 17 + "px",
        top: this.theY + this.height - 17 + "px",
      };
    },
    chartActive() {
      return this.$store.getters.getChartActive;
    },
  },
  watch: {
    values(val) {
      if (val) this.throttleUpdateChart();
    },
    columns(val) {
      if (val) this.throttleUpdateChart();
    },
    type(val) {
      if (val) this.throttleUpdateChart();
    },
    clusterCount(val) {
      if (val) this.throttleUpdateChart();
    },
    title(val) {
      if (val) this.throttleUpdateChart();
    },
    titleLeft(val) {
      if (val) this.throttleUpdateChart();
    },
    titleColor(val) {
      if (val) this.throttleUpdateChart();
    },
    darkMode(val) {
      if (val) this.throttleUpdateChart();
    },
    fontsize(val) {
      if (val) this.throttleUpdateChart();
    },
    xAxisShow(val) {
      if (val != null) this.throttleUpdateChart();
    },
    xAxisName(val) {
      if (val != null) this.throttleUpdateChart();
    },
    xAxisNameLocation(val) {
      if (val) this.throttleUpdateChart();
    },
    xAxisNameColor(val) {
      if (val) this.throttleUpdateChart();
    },
    xAxisOffset(val) {
      if (val) this.throttleUpdateChart();
    },
    xAxisFontSize(val) {
      if (val) this.throttleUpdateChart();
    },
    xAxisPosition(val) {
      if (val) this.throttleUpdateChart();
    },
    yAxisShow(val) {
      if (val != null) this.throttleUpdateChart();
    },
    yAxisName(val) {
      if (val != null) this.throttleUpdateChart();
    },
    yAxisNameLocation(val) {
      if (val) this.throttleUpdateChart();
    },
    yAxisNameColor(val) {
      if (val) this.throttleUpdateChart();
    },
    yAxisOffset(val) {
      if (val) this.throttleUpdateChart();
    },
    yAxisFontSize(val) {
      if (val) this.throttleUpdateChart();
    },
    yAxisPosition(val) {
      if (val) this.throttleUpdateChart();
    },
    legendType(val){
      if (val != null)  this.throttleUpdateChart()
    },
    legendShow(val){
      if(val != null) this.throttleUpdateChart()
    },
    legendLeft(val){
      if(val != null) this.throttleUpdateChart();
    },
    legendTop(val){
      if(val != null) this.throttleUpdateChart()
    },
    legendWidth(val){
      if(val != null) this.throttleUpdateChart()
    },
    legendHeight(val){
      if(val != null) this.throttleUpdateChart()
    },
    legendOrient(val){
      if(val) this.throttleUpdateChart()
    },
    legendColor(val){
      if(val) this.throttleUpdateChart()
    },
    legendFontSize(val){
      if(val) this.throttleUpdateChart()
    }
  },
  data() {
    return {
      biasX: 0,
      biastY: 0,

      resizeStatus: false,
      resizeType: null,
      resizeBiasX: 0,
      resizeBiasY: 0,

      fixWidth: 0,
      fixHeight: 0,
      fixTheX: 0,
      fixTheY: 0,
    };
  },
  mounted() {
    this.initChart();
    this.throttleUpdateChart = this.throttle(this.updateChart, 1000);
  },
  methods: {
    throttle(fn, wait) {
      var timer = null;
      return function () {
        var context = this;
        var args = arguments;
        if (!timer) {
          timer = setTimeout(function () {
            fn.apply(context, args);
            timer = null;
          }, wait);
        }
      };
    },
    genUrl(encoded) {
      const dataBlob = new Blob([`\ufeff${encoded}`], {
        type: "text/plain;charset=utf-8",
      }); //返回的格式
      return window.URL.createObjectURL(dataBlob);
    },
    chartTransferArr(chart) {
      let valueNameList = [];

      let columnName = chart.axis[0]
        ? this.chartActive.axis[0].fieldName
        : "column";

      let data = {
        data: {},
      };

      for (let val of chart.value) {
        valueNameList.push(val.fieldName);
      }

      let title = chart.title;

      data["data"][columnName] = chart.columns;

      for (let i = 0; i < valueNameList.length; i++) {
        data["data"][valueNameList[i]] = chart.values[i];
      }

      data["title"] = title;

      return data;
    },
    downloadByPeople() {
      let data = Utils.chartTransferArr(this.chartActive);

      this.$axios.post("/download", data).then((res) => {
        if (res.code == 200) {
          this.$message({
            type: "success",
            message: res.msg,
          });

          const url = this.genUrl(res.data, {}); //{}指的是表头，res.data.data.workhour_csv_data是后台返回来的数据
          const a = document.createElement("a");
          a.href = url;
          a.download = data.title + ".csv";
          a.click();
          window.URL.revokeObjectURL(url);
        } else this.$message.error(res.msg);
      });
    },
    setActive(val) {
      this.$emit("set-active", this.canvasIndex, this.chartIndex, val);
    },
    setMoveActive(val) {
      this.$emit("set-move-active", this.canvasIndex, this.chartIndex, val);
    },
    updateChart() {
      let option = this.getOption();

      if (!option) return;

      //   this.echarts.setOption(option);
      this.$store.commit("setEchartOption", option);
    },
    removeChart() {
      console.log("removeChart");
      this.$store.commit("removeChart");
    },
    resizeDown(e, type) {
      let data = {
        type,
        startPointX: e.clientX,
        startPointY: e.clientY,
        fixWidth: this.chartActive.width,
        fixHeight: this.chartActive.height,
        fixTheX: this.chartActive.theX,
        fixTheY: this.chartActive.theY,
      };

      this.$emit("set-resize-type", data);
    },
    resizeUp() {
      this.resizeStatus = false;
      this.echarts.resize({
        animation: {
          duration: 2,
        },
      });
    },
    getCommonOption() {
      let option = {
        title: {
          text: this.title,
          left: this.titleLeft + "%",
          textStyle: {
            fontSize: this.fontsize,
            color: this.titleColor,
          },
        },
        legend: {
          data: [],
          show: this.legendShow,
          type: this.legendType,
          orient: this.legendOrient,
          left: this.legendLeft + '%',
          top: this.legendTop + '%',
          width: this.legendWidth + '%',
          height: this.legendHeight + '%',
          textStyle:{
            fontSize: this.legendFontSize,
            color: this.legendColor,
          }
        },
        xAxis: {
          show: this.xAxisShow,
          name: this.xAxisName,
          nameLocation: this.xAxisNameLocation,
          offset: this.xAxisOffset,
          position: this.xAxisPosition,
          nameTextStyle: {
            color: this.xAxisNameColor,
            fontSize: this.xAxisFontSize,
          },
        },
        yAxis: {
          show: this.yAxisShow,
          name: this.yAxisName,
          nameLocation: this.yAxisNameLocation,
          offset: this.yAxisOffset,
          position: this.yAxisPosition,
          nameTextStyle: {
            color: this.yAxisNameColor,
            fontSize: this.yAxisFontSize,
          },
        },
        dataZoom: [
          {
            type: "slider",
            show: true,
            xAxisIndex: [0],
            start: 0,
            end: 35,
          },
          {
            type: "slider",
            show: false,
            yAxisIndex: [0],
            left: "93%",
            start: 0,
            end: 100,
          },
        ],
        toolbox: {
          feature: {
            saveAsImage: {
              show: true,
              title: "保存为图片",
            },
            dataView: {
              show: true,
              title: "数据表",
            },
          },
        },
        grid: {
          left: "20%",
          width: "70%",
        },
        tooltip: {
          trigger: "item",
        },
        series: [],
      };
      if (!this.chartActive) return null;

      for (let i = 0; i < this.chartActive.values.length; i++) {
        let obj = {};
        option.legend.data.push(this.value[i] ? this.value[i].fieldName : "");
        obj.name = this.value[i] ? this.value[i].fieldName : "";

        obj.type = this.type;

        if (this.type == "bar-cross") obj.type = "bar";
        else if (this.type == "area") {
          obj.type = "line";
          obj.areaStyle = {};
        } else if (this.type == "matching") {
          obj.type = "scatter";
        } else if (this.type == "forecast") obj.type = "line";
        obj.data = this.values[i];

        option.series.push(obj);
      }

      return option;
    },
    pieOption() {
      let option = this.getCommonOption();
      let legend = option.legend;
      let title = option.title;
      let tooltip = option.tooltip;
      let grid = option.grid;
      let toolbox = option.toolbox;
      let data = [];

      legend.data = [];

      for (let i = 0; i < this.values.length; i++) {
        for (let j = 0; j < this.values[i].length; j++) {
          data.push({
            value: this.values[i][j],
            name: this.columns[j],
          });

          legend.data.push(this.columns[j]);
        }
      }
      return {
        title,
        legend,
        tooltip,
        toolbox,
        grid,
        series: [
          {
            name: this.value[0] ? this.value[0].fieldName : null,
            type: "pie",
            radius: "50%",
            data: data,
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: "rgba(0, 0, 0, 0.5)",
              },
            },
          },
        ],
      };
    },
    barCrossOption() {
      let option = this.getCommonOption();
      let legend = option.legend;
      let title = option.title;
      let grid = option.grid;
      let toolbox = option.toolbox;
      let dataZoom = option.dataZoom;
      let series = option.series;
      let xAxis = option.xAxis
      let yAxis = option.yAxis
      yAxis.data = this.columns
      series = this.setBigDataOption(series);

      return {
        title,
        toolbox,
        legend,
        grid,
        dataZoom,
        series,
        xAxis,
        yAxis,
        // yAxis: {
        //   data: this.columns,
        // },
      };
    },
    areaOption() {
      let option = this.getCommonOption();
      let legend = option.legend;
      let title = option.title;
      let grid = option.grid;
      let toolbox = option.toolbox;
      let dataZoom = option.dataZoom;
      let series = option.series;
      let xAxis = option.xAxis
      xAxis.data = this.columns
      let yAxis = option.yAxis
      series.areaStyle = {};
      series = this.setBigDataOption(series, "area");

      return {
        title,
        toolbox,
        legend,
        grid,
        dataZoom,
        series,
        tooltip: {},
        xAxis,
        yAxis,
      };
    },
    matchingOption() {
      let option = this.getCommonOption();
      let legend = option.legend;
      let title = option.title;
      let grid = option.grid;
      let toolbox = option.toolbox;
      let dataZoom = option.dataZoom;
      let series = option.series;
      let xAxis = option.xAxis
      xAxis.data = this.columns
      let yAxis = option.yAxis

      if (series[1]) {
        series[1].type = "line";
        series[1].name = "拟合";
        legend.data[1] = "拟合";
      }

      series = this.setBigDataOption(series);

      return {
        title,
        toolbox,
        legend,
        grid,
        dataZoom,
        series,
        xAxis,
        yAxis,
      };
    },
    clusterOption() {
      let option = this.getCommonOption();

      // let legend = option.legend;
      let title = option.title;
      let grid = option.grid;
      let toolbox = option.toolbox;
      let dataZoom = option.dataZoom;
      let series = {
        type: "scatter",
        encode: { tooltip: [0, 1] },
        symbolSize: 15,
        itemStyle: {
          borderColor: "#555",
        },
        datasetIndex: 1,
      };

      let CLUSTER_COUNT = this.clusterCount;
      let DIENSIION_CLUSTER_INDEX = 2;
      let COLOR_ALL = [
        "#37A2DA",
        "#e06343",
        "#37a354",
        "#b55dba",
        "#b5bd48",
        "#8378EA",
        "#96BFFF",
      ];
      let pieces = [];
      for (var i = 0; i < CLUSTER_COUNT; i++) {
        pieces.push({
          value: i,
          label: "cluster " + i,
          color: COLOR_ALL[i],
        });
      }
      let visualMap = {
        type: "piecewise",
        top: "middle",
        min: 0,
        max: CLUSTER_COUNT,
        left: 10,
        splitNumber: CLUSTER_COUNT,
        dimension: DIENSIION_CLUSTER_INDEX,
        pieces: pieces,
      };
      let xAxis = option.xAxis;
      let yAxis = option.yAxis;

      let data = [];
      let length = this.values[0] ? this.values[0].length : 0;
      for (let i = 0; i < length; i++) {
        let list = [];

        let value = Number.parseInt(this.values[0][i]);
        let columns = Number.parseInt(this.columns[i]);

        if (Number.isNaN(value)) continue;
        if (Number.isNaN(columns)) continue;

        list.push(value);
        list.push(columns);

        data.push(list);
      }

      let dataset = [
        {
          source: data,
        },
        {
          transform: {
            type: "ecStat:clustering",
            // print: true,
            config: {
              clusterCount: CLUSTER_COUNT,
              outputType: "single",
              outputClusterIndexDimension: DIENSIION_CLUSTER_INDEX,
            },
          },
        },
      ];

      return {
        // legend,
        title,
        grid,
        toolbox,
        dataZoom,
        series,
        visualMap,
        xAxis,
        yAxis,
        dataset,
      };
    },
    getOption() {
      let option = this.getCommonOption();

      if (!option) return;

      let legend = option.legend;
      let title = option.title;
      let grid = option.grid;
      let toolbox = option.toolbox;
      let dataZoom = option.dataZoom;
      let series = option.series;
      let xAxis = option.xAxis;
      let yAxis = option.yAxis
      xAxis.data = this.columns;
      // legend.data = [];

      if (this.type == "pie") {
        return this.pieOption();
      } else if (this.type == "bar-cross") {
        return this.barCrossOption();
      } else if (this.type == "area") {
        return this.areaOption();
      } else if (this.type == "matching") {
        return this.matchingOption();
      } else if (this.type == "cluster") {
        return this.clusterOption();
      }

      series = this.setBigDataOption(series);

      return {
        title,
        toolbox,
        legend,
        grid,
        dataZoom,
        series,
        xAxis,
        yAxis,
        tooltip: {},
        // yAxis: {},
        // xAxis: {
        //   data: this.columns,
        // },
      };
    },
    setBigDataOption(series) {
      if (series[0] && series[0].data.length > 100000)
        for (let i = 0; i < series.length; i++) {
          series[i].large = true;
          series[i].sampling = "lttb";
        }

      return series;
    },
    initChart() {
      let chart = $(this.$el).children(".chart")[0];
      let data = {
        chart,
        $echarts: this.$echarts,
      };
      //   this.echarts = this.$echarts.init(chart);
      this.$store.commit("setChartActiveEchart", data);
      let option = this.getOption();
      // 使用刚指定的配置项和数据显示图表。

      this.$store.commit("setEchartOption", option);
      //   this.echarts.setOption(option);
    },
    hasXCross() {
      let chartStartX = this.positionX - this.biasX;
      let chartEndX = chartStartX + this.width;

      if (chartStartX < this.canvasStartX || chartEndX > this.canvasEndX)
        return true;
      return false;
    },
    hasYCross() {
      let chartStartY = this.positionY - this.biasY + this.canvasStartY;
      let chartEndY = chartStartY + this.height;

      if (chartStartY < this.canvasStartY || chartEndY > this.canvasEndY)
        return true;

      return false;
    },
    move() {
      if (this.moveActive && !this.hasXCross()) {
        let theX = this.positionX - this.biasX;
        let data = {
          theX,
        };
        this.$store.commit("setChartSize", data);
        // this.theX = this.positionX - this.biasX;
        // this.theY = this.positionY - this.biasY;
      }

      if (this.moveActive && !this.hasYCross()) {
        let theY = this.positionY - this.biasY;
        let data = {
          theY,
        };
        this.$store.commit("setChartSize", data);
      }
    },
    down(e) {
      this.biasX = e.clientX - this.theX;
      this.biasY = e.clientY - this.theY;
      this.setActive(true);
      this.setMoveActive(true);
    },
    up() {
      this.setMoveActive(false);
    },
  },
};
</script>

<style scoped>
img {
  width: 20px;
}

.leftTop,
.rightTop,
.leftBottom,
.rightBottom {
  user-select: none;
  -webkit-user-drag: none;
}

.leftTop:hover {
  cursor: nw-resize;
}

.rightTop:hover {
  cursor: ne-resize;
}

.leftBottom:hover {
  cursor: sw-resize;
}

.rightBottom:hover {
  cursor: se-resize;
}

.close {
  position: absolute;
  right: 0px;
}

.close {
  left: 270px;
  top: 10px;
}
</style>